let http = require('http');
let url = require('url');
let methods = require('methods')
let fs = require('fs')
let path = require('path');
let mime = require('mime');


function application() {
  let app = (req, res) => {
    let {pathname} = url.parse(req.url, true) || {};
    let requestMethod = req.method.toLowerCase();
    /* for (let i = 0; i < app.routes.length; i++) {
       let layer = app.routes[i];
       let {path, handler, method} = layer;
       if (path.params) {
         let matches = pathname.match(path);

         if (matches) {
           let [, ...list] = matches;
           req.params = path.params.reduce((memo, current, index) => (memo[current] = list[index], memo), {})
           return handler(req, res);
         }

       }
       if ((pathname === path || path === '*') && requestMethod === method || method === 'all') {
         handler(req, res);
         return;
       }

     }
 */
    let index = 0;
    function next(err) {
      if (index === app.routes.length) {
        res.statusCode = 404;
        console.log('路由没有找到');
        return res.end();
      }
      let {method, path, handler} = app.routes[index++];
      if (err) {
        if (method === 'middleware' && handler.length === 4) {
          return handler(err, req, res, next);
        } else {
          next(err);
        }
      } else {
        if (method === 'middleware') {
          if (path === pathname || path === '/' || pathname.startsWith(path + '/')) {
            return handler(req, res, next);
          } else {
            next();
          }
        } else {
          if (path.params) {
            let matches = pathname.match(path);

            if (matches) {
              let [, ...list] = matches;
              req.params = path.params.reduce((memo, current, index) => (memo[current] = list[index], memo), {})
              return handler(req, res);
            }

          }
          console.log(path,pathname);
          if ((pathname === path || path === '*') && (requestMethod === method || method === 'all')) {
            return handler(req, res);
          }
          next();
        }
      }

    }

    next();

    // console.log(`执行到这里了`);
    // res.end(`cannot ${requestMethod} ${pathname}`)

  }
  app.routes = [];
  [...methods, 'all'].forEach(method => {
    app[method] = function (path, handler) {
      let params = [];
      if (path.includes(':')) {
        path = path.replace(/:([^\/]*)/g, function () {
          params.push(arguments[1]);
          return '([^\/]*)'
        });

        path = new RegExp(path);
        path.params = params;


      }

      let layer = {
        path,
        method: method,
        handler
      };
      app.routes.push(layer)
    }
  })

  app.use = function (path, handler) {
    if (typeof handler != 'function') {
      handler = path;
      path = '/';
    }
    let layer = {
      method: 'middleware',
      path,
      handler
    }
    app.routes.push(layer);

  }
  app.listen = function () {
    let server = http.createServer(app);
    server.listen(...arguments);
  }
  app.use(function (req, res, next) {
    res.on("close",function(){
      console.log("close")
    })
    let url = require('url')
    let {query, pathname} = url.parse(req.url, true)
    req.query = query;
    req.path = pathname;
    res.send = function (value) {
      if (typeof value === 'object') {
        res.setHeader('Content-Type', 'application/json:charset=utf-8')
        res.end(JSON.stringify(value))
      } else if (typeof value === 'number') {
        res.statusCode = value;
        let status = require('_http_server').STATUS_CODES;
        res.end(status[value]);
      } else if (typeof value === 'string' || Buffer.isBuffer(value)) {
        res.setHeader('Content-Type', 'text/html:charset=utf-8')
        res.end(value);
      }


    }
    res.sendFile = function (p) {

      try{
        res.setHeader('Content-Type', mime.getType(p) + ';charset=utf-8')
        fs.createReadStream(p).pipe(res);

      }catch (e) {
        console.log(e)
        res.send(404)
      }
    }
    next();
  })

  return app;
}
application.static = function(root){
  return function (req, res,next) {
    let p = req.path;
    let absPath = path.join(root,p);
    console.log('absPath:',absPath);
    fs.stat(absPath,(err,statObj)=>{
      if (err){
        return next();
      }
      if(statObj.isFile()){
        try{
          console.log(absPath)
          fs.createReadStream(absPath).pipe(res);
        }catch (e) {
          console.log(e)
        }
      }
    })
  }
}
module.exports = application;
